package cn.duhengkui.national.valuelist.core.data.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;


/**   
 * <table border="1">
 *	<tr><td>包名称：</td><td>cn.duhengkui.national.valuelist.core.data.util</td></tr>
 *	<tr><td>类名称：</td><td>GenericsUtils</td></tr>
 *	<tr><td>类描述：</td><td>用于获取DAO方法的反射信息</td></tr>
 *	<tr><td>创建人：</td><td>杜恒奎</td></tr>
 *  <tr><td>创建时间：</td><td>2018年6月7日/下午3:10:00</td></tr> 
 *  <tr><td>版本：</td><td>1.0.0</td></tr>
 * </table>   
 *     
 */
public class GenericsUtils {
	
	/**
	 * 获取DAO的泛型类型
	 * @param clazz 接口Class
	 * @return
	 */
	public static Class<?> getClassGenricType(Class<?> clazz) {
		return getClassGenricType(clazz, 0);
	}
	
	/**
	 * 获取DAO的泛型类型
	 * @param clazz 接口Class
	 * @param index 接口数组下标
	 * @return
	 */
	public static Class<?> getClassGenricType(Class<?> clazz, int index) {
		Type genType = clazz.getGenericInterfaces()[0];
		if (!(genType instanceof ParameterizedType)) {
			return Object.class;
		}
		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
		if (index >= params.length || index < 0) {
			throw new RuntimeException();
		}
		if (!(params[index] instanceof Class)) {
			return Object.class;
		}
		return (Class<?>) params[index];
	}
	
	/**
	 * 获取超类接口
	 * @param clazz 接口Class
	 * @param index 接口数组下标
	 * @return
	 */
	public static Class<?> getSuperClassGenricType(Class<?> clazz, int index) {
		Type genType = clazz.getGenericSuperclass();
		if (!(genType instanceof ParameterizedType)) {
			return Object.class;
		}
		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
		if (index >= params.length || index < 0) {
			throw new RuntimeException();
		}
		if (!(params[index] instanceof Class)) {
			return Object.class;
		}
		return (Class<?>) params[index];
	}

	/**
	 * 获取超类接口
	 * @param clazz 接口Class
	 * @return
	 */
	public static Class<?> getSuperClassGenricType(Class<?> clazz) {
		return getSuperClassGenricType(clazz, 0);
	}

	public static Class<?> getMethodGenericReturnType(Method method, int index) {
		Type returnType = method.getGenericReturnType();
		if (returnType instanceof ParameterizedType) {
			ParameterizedType type = (ParameterizedType) returnType;
			Type[] typeArguments = type.getActualTypeArguments();
			if (index >= typeArguments.length || index < 0) {
				throw new RuntimeException();
			}
			return (Class<?>) typeArguments[index];
		}
		return Object.class;
	}

	/**
	 * 获取方法返回值类型
	 * @param method 方法
	 * @return
	 */
	public static Class<?> getMethodGenericReturnType(Method method) {
		return getMethodGenericReturnType(method, 0);
	}

	/**
	 * 获取方法所有参数
	 * @param method 方法
	 * @param index 参数数量
	 * @return
	 */
	public static List<Class<?>> getMethodGenericParameterTypes(Method method, int index) {
		List<Class<?>> results = new ArrayList<>();
		Type[] genericParameterTypes = method.getGenericParameterTypes();
		if (index >= genericParameterTypes.length || index < 0) {
			throw new RuntimeException();
		}
		Type genericParameterType = genericParameterTypes[index];
		if (genericParameterType instanceof ParameterizedType) {
			ParameterizedType aType = (ParameterizedType) genericParameterType;
			Type[] parameterArgTypes = aType.getActualTypeArguments();
			for (Type parameterArgType : parameterArgTypes) {
				Class<?> parameterArgClass = (Class<?>) parameterArgType;
				results.add(parameterArgClass);
			}
			return results;
		}
		return results;
	}

	/**
	 * 获取方法所有参数
	 * @param method 方法
	 * @return
	 */
	public static List<Class<?>> getMethodGenericParameterTypes(Method method) {
		return getMethodGenericParameterTypes(method, 0);
	}

	public static Class<?> getFieldGenericType(Field field, int index) {
		Type genericFieldType = field.getGenericType();

		if (genericFieldType instanceof ParameterizedType) {
			ParameterizedType aType = (ParameterizedType) genericFieldType;
			Type[] fieldArgTypes = aType.getActualTypeArguments();
			if (index >= fieldArgTypes.length || index < 0) {
				throw new RuntimeException();
			}
			return (Class<?>) fieldArgTypes[index];
		}
		return Object.class;
	}

	/**
	 * 获取属性类型
	 * @param field 属性
	 * @return
	 */
	public static Class<?> getFieldGenericType(Field field) {
		return getFieldGenericType(field, 0);
	}
}